package com.ccloud.common.core.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author chentailai
 * @version V1.0
 * @Project ccloud-parent
 * @Title ValueUtils.java
 * @Description 常用值类型转换 （有限类型）
 * @Package com.hd.common.utils
 * @date 2020/12/24 11:47 上午
 */
@Slf4j
public final class ValueUtils {


    /**
     * 如果异常，返回0值。
     *
     * @param obj
     * @return
     */
    public static Double parseDoubleForDecorator(Object obj) {
        if (obj == null) {
            return 0d;
        }
        if (obj instanceof Double) {
            return (Double) obj;
        }
        if (obj instanceof String) {
            try {
                return Double.valueOf(obj.toString().trim());
            } catch (NumberFormatException e) {
                log.error("NumberFormatException ", e);
                return 0d;
            }
        }
        if (obj instanceof Integer) {
            Integer objInt = (Integer) obj;
            return objInt.doubleValue();
        }
        if (obj instanceof Long) {
            Long objLong = (Long) obj;
            return objLong.doubleValue();
        }
        if (obj instanceof BigDecimal) {
            BigDecimal objLong = (BigDecimal) obj;
            return objLong.doubleValue();
        }
        return 0d;
    }


    /**
     * 转换Double
     *
     * @param obj
     * @return return null if parse failed
     * @author chentl
     * @Description:
     */
    public static Double parseDouble(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Double) {
            return (Double) obj;
        }
        if (obj instanceof String) {
            try {
                return Double.valueOf(obj.toString().trim());
            } catch (NumberFormatException e) {
                return null;
            }
        }
        if (obj instanceof Integer) {
            Integer objInt = (Integer) obj;
            return objInt.doubleValue();
        }
        if (obj instanceof Long) {
            Long objLong = (Long) obj;
            return objLong.doubleValue();
        }
        if (obj instanceof BigDecimal) {
            return ((BigDecimal) obj).doubleValue();
        }
        return null;
    }

    /**
     * 转换Integer
     *
     * @param obj
     * @return return null if parse failed
     * @Description:
     */
    public static Integer parseInteger(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Integer) {
            return (Integer) obj;
        }
        if (obj instanceof String) {
            try {
                return Integer.valueOf(obj.toString().trim());
            } catch (NumberFormatException e) {
                return null;
            }
        }
        if (obj instanceof Double) {
            Double objDouble = (Double) obj;
            return objDouble.intValue();
        }
        if (obj instanceof Long) {
            Long objLong = (Long) obj;
            return objLong.intValue();
        }
        if (obj instanceof Object) {
            return Integer.parseInt(obj.toString());
        }
        return null;
    }

    /**
     * 转换String
     *
     * @param obj
     * @return return null if parse failed
     * @Description:
     */
    public static String parseString(Object obj) {
        if (obj == null) {
            return StringUtils.EMPTY;
        }
        return String.valueOf(obj);
    }

    /**
     * 转换Long
     *
     * @param obj
     * @return return null if parse failed
     * @Description:
     */
    public static Long parseLong(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Integer) {
            Integer objInt = (Integer) obj;
            return objInt.longValue();
        }
        if (obj instanceof String) {
            try {
                return Long.valueOf(obj.toString().trim());
            } catch (NumberFormatException e) {
                log.error("NumberFormatException ", e);
                return null;
            }
        }
        if (obj instanceof Double) {
            Double objDouble = (Double) obj;
            return objDouble.longValue();
        }
        if (obj instanceof Long) {
            return (Long) obj;
        }
        return null;
    }

    /**
     * 转换Boolean类型
     *
     * @param obj
     * @return
     * @Description:
     */
    public static Boolean parseBoolean(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Boolean) {
            return (Boolean) obj;
        }
        if (obj instanceof Integer) {
            Integer objInt = (Integer) obj;
            return objInt != 0;
        }
        if (obj instanceof String) {
            try {
                return Boolean.valueOf(obj.toString().trim());
            } catch (NumberFormatException e) {
                log.error("NumberFormatException ", e);
                return null;
            }
        }
        if (obj instanceof Double) {
            Double objDouble = (Double) obj;
            return objDouble != 0D;
        }

        if (obj instanceof Long) {
            Long longObj = (Long) obj;
            return longObj != 0;
        }
        return null;
    }

    /**
     * 格式化小数字符串
     *
     * @param obj
     * @param w   保留小数位数
     * @return
     */
    public static String parseFloatString(Object obj, int w) {
        if (obj == null) {
            return StringUtils.EMPTY;
        }

        final double zVal = .0d;
        double val = zVal;
        try {
            val = Double.parseDouble(obj.toString());
        } catch (Exception e) {
            return StringUtils.EMPTY;
        }

        String rStr = "";
        double uVal = .0d;
        if (w == 0) {
            uVal = 1d;
            rStr = "<1";
        } else if (w > 0) {
            final String zStr = String.format("%0" + w + "d", 0);
            uVal = Double.valueOf("." + zStr.substring(1) + "1d");
            rStr = "<" + uVal;
        } else {
            return StringUtils.EMPTY;
        }

        return (val > zVal && val < uVal) ? rStr : String.format("%." + w + "f", obj);
    }

    public static Integer parseInt(Object obj) {
        double value = parseDouble(obj);
        return parseInteger(value);
    }


    public static BigDecimal RetainBigDecimals(BigDecimal bigDecimal) {
        if (bigDecimal == null) {
            return bigDecimal;
        } else {
            return bigDecimal.setScale(4, BigDecimal.ROUND_UP);
        }
    }


    public static String Retain2BigDecimals(String value) {
        if (StringUtils.isNotBlank(value)) {
            try {
                return new BigDecimal(value).setScale(2, BigDecimal.ROUND_DOWN).toString();
            } catch (Exception e) {
                return "";
            }
        } else {
            return value;
        }
    }


    /**
     * 转换cm3 为 m3
     *
     * @param value
     * @return
     */
    public static BigDecimal transferCubicMeter(BigDecimal value, Integer baseNumber, Integer pow) {
        if (value == null) {
            log.error("params obj is null");
            return null;
        }
        return value.multiply(new BigDecimal(Math.pow(baseNumber, pow))).setScale(4, BigDecimal.ROUND_HALF_UP);
    }

    public static String clearMiddleBrackets(String str) {
        return str.replaceAll("\\[([^\\]]*)\\]", "$1");
    }

    /**
     * @title: getIntHalfUp
     * @description: 四舍五入取整
     * @author: weiyang
     * @date: 2020/7/16
     * @param: value
     * @return: java.math.BigDecimal
     */
    public static BigDecimal getIntHalfUp(BigDecimal value) {
        if (value == null) {
            log.error("value obj is null");
            return null;
        }
        return value.setScale(0, BigDecimal.ROUND_HALF_UP); // 四舍五入取整
    }

    /**
     * @title: getHalfUp
     * @description: 四舍五入
     * @author: weiyang
     * @date: 2020/7/16
     * @param: value
     * @return: java.math.BigDecimal
     */
    public static BigDecimal getHalfUp(BigDecimal value) {
        if (value == null) {
            log.error("value obj is null");
            return null;
        }
        return value.setScale(2, BigDecimal.ROUND_HALF_UP); // 四舍五入取整
    }


    /**
     * rounding:(保留2位小数  小数点后全为0直接取整数).
     *
     * @param big
     * @return
     * @since JDK 1.8
     */
    public static BigDecimal rounding(BigDecimal big) {
        if (big != null) {
            BigDecimal in = big.setScale(0, BigDecimal.ROUND_DOWN);
            if (big.subtract(in).toString().equals("0.0000")) {
                return in;
            } else {
                return new BigDecimal(big.setScale(2, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
            }
        } else {
            return null;
        }

    }

    /**
     * rounding:(保留4位小数  小数点后全为0直接取整数).
     *
     * @param big
     * @return
     * @since JDK 1.8
     */
    public static BigDecimal roundingExt(BigDecimal big) {
        if (big != null) {
            BigDecimal in = big.setScale(0, BigDecimal.ROUND_DOWN);
            if (big.subtract(in).toString().equals("0.0000")) {
                return in;
            } else {
                return big.setScale(4, BigDecimal.ROUND_HALF_UP).stripTrailingZeros();
            }
        } else {
            return null;
        }

    }


    public static void main(String[] args) {
        System.out.println(rounding(new BigDecimal(360.0000)));
        System.out.println(rounding(new BigDecimal(360.000)));
        System.out.println(rounding(new BigDecimal(360.00)));
        System.out.println(rounding(new BigDecimal(360.1000)));
        System.out.println(rounding(new BigDecimal(360.0001)));
        System.out.println(rounding(new BigDecimal(360.0010)));
        System.out.println(rounding(new BigDecimal(360.0100)));
        System.out.println(rounding(new BigDecimal(360.1000)));
        System.out.println(rounding(new BigDecimal(360.1100)));
        System.out.println(rounding(new BigDecimal(360.1110)));
        System.out.println(rounding(new BigDecimal(360.1010)));
    }

    /**
     * @title: 判断是否为正整数或浮点数
     * @description:
     * @author: whdsj
     * @date: 2020/7/16
     * @param: value
     * @return: boolean
     */
    public static boolean isNumeric(String str) {
        // 判断正整数正则
        Pattern patternInteger = Pattern.compile("^\\d+(\\.\\d+)?$");
        // 判断浮点数正则
        Pattern patternFloat = Pattern.compile("^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$");
        return patternFloat.matcher(str).matches() || patternInteger.matcher(str).matches();
    }

    /**
     * @title: hashKeyForDisk
     * @description: 生成字符串的Hash值
     * @author: weiyang
     * @date: 2020/8/13 15:59
     * @param: key
     * @return: java.lang.String
     */
    public static String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }

    /**
     * @title: bytesToHexString
     * @description:
     * @author: weiyang
     * @date: 2020/8/13
     * @param: bytes
     * @return: java.lang.String
     */
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * @return void
     * @Author whdsj
     * @Description map 拷贝
     * @Name assignMap
     * @Create 10:41 2020/12/14 0014
     * @Param [source, target]
     **/
    public static void assignMap(Map source, Map target) {
        if (target == null) target = new HashMap(1024);
        if (source == null) return;

        Iterator it = source.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Object key = entry.getKey();
            target.put(key, source.get(key) != null ? source.get(key) : "");

        }
    }

    /**
     * @return java.lang.String
     * @author chentailai
     * @description 计算百分比
     * @date 2020/12/28 3:11 下午
     * @params [first, second]
     */
    public static String getRate(Integer first, Integer second, Integer digit) {
        if (first == null || second == null) return "";
        NumberFormat numberFormat = NumberFormat.getInstance();
        //精确位
        numberFormat.setMaximumFractionDigits(digit);


        return numberFormat.format((float) first / (float) second * Math.pow(10, digit));
    }

    /**
     * @return java.lang.String
     * @description 获取坐标
     * @date 2021/1/6 8:47 上午
     * @params [c]
     */
    public static Double getCoordinate(String c) {
        if (StringUtils.isBlank(c) || ValueUtils.parseDouble(c) == 0) return null;

        int index = c.length() - 6;
        String first = c.substring(0, index);
        String second = c.substring(index);
        return parseDoubleForDecorator(first + "." + second);
    }


    /**
     * @return void
     * @author chentailai
     * @description 不同类型属性 初始值
     * @date 2021/1/8 3:07 下午
     * @params [o]
     */
    public static Object initVal(Object o) {
        if (o instanceof Double) {
            o = (double) 0;
        } else if (o instanceof String) {
            o = "";
        } else if (o instanceof Date) {
            o = null;
        } else if (o instanceof Long) {
            o = 0L;
        }
        return o;
    }


}
